package com.heatup.apt.management.task;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.heatup.apt.common.constants.OrderContants;
import com.heatup.apt.common.dao.*;
import com.heatup.apt.common.dao.user.UserInfoMapper;
import com.heatup.apt.common.util.DateUtil;
import com.heatup.apt.common.util.SmsUtil;
import com.heatup.apt.management.service.TemplateSendService;
import com.heatup.apt.management.util.ManageConfigPropertiesUtil;
import com.heatup.apt.model.SmsLog;
import com.heatup.apt.model.api.OrderInfoResultModel;
import com.heatup.apt.model.channer.CourseNoticeInfo;
import com.heatup.apt.model.coach.CoachCourseInfo;
import com.heatup.apt.model.company.CompanyStaffConsume;
import com.heatup.apt.model.coupon.CouponDetail;
import com.heatup.apt.model.course.CourseInfo;
import com.heatup.apt.model.order.OrderCourseDetailInfo;
import com.heatup.apt.model.order.OrderRefund;
import com.heatup.apt.model.user.UserInfo;
import com.heatup.apt.model.user.UserProductService;

import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
@EnableScheduling
public class OrderJobServiceTask {

	private final static Logger log = LoggerFactory.getLogger(OrderJobServiceTask.class);
	@Autowired
	private OrderInfoResultMapper orderInfoResultMapper;

	@Autowired
	private OrderInfoMapper orderInfoMapper;

	@Autowired
	private TemplateSendService templateSendService;

	@Autowired
	private CouponDetailMapper couponDetailMapper;

	@Autowired
	private UserInfoMapper userInfoMapper;

	@Autowired
	private CourseNoticeInfoMapper courseNoticeInfoMapper;

    @Autowired
    private CourseInfoMapper courseInfoMapper;

	@Autowired
	private CompanyStaffConsumeMapper companyStaffConsumeMapper;

    @Autowired
    private SmsLogMapper smsLogMapper;

	private final String TOKEN_UPDATE_FLAG = ManageConfigPropertiesUtil.getString("token_update_flag").trim();

	/**
	 * 自动取消团课排队订单
	 */
	@Scheduled(cron = "0 */5 * * * ?") // test每隔5分钟调用
	public void autoCancelWaitTeamOrder() {

		// String TOKEN_UPDATE_FLAG =
		// ManageConfigPropertiesUtil.getString("token_update_flag").trim();

		// 1测试/正式环境才启动定时器
		if ("1".equals(TOKEN_UPDATE_FLAG)) {
			log.info("=============autoCancelWaitTeamOrder start=============");
			try{
			List<OrderInfoResultModel> orderInfoResultModels = orderInfoResultMapper.selectAutoCancelWaitTeamOrder();
			if (orderInfoResultModels != null && orderInfoResultModels.size() > 0) {
				log.info("自动取消团课排队订单任务-size : " + orderInfoResultModels.size());
				for (OrderInfoResultModel orderInfo : orderInfoResultModels) {

					// 取消订单
					Date updateTime = new Date();
					orderInfo.setOrderStatus(OrderContants.OrderStatus.CANCEL.getStatus());
					orderInfo.setUserCancelTime(updateTime);
					orderInfo.setCancelBackmoney(1);
					orderInfo.setCancel(2);
					orderInfo.setUpdatedTime(updateTime);
					orderInfo.setUpdatedBy(-1);
					orderInfoMapper.updateSelectiveById(orderInfo);

					//企业支付的可退款订单 退款记录
					if (orderInfo.getPayType() == OrderContants.PAY_TYPE_COMPANY_ACCOUNT && orderInfo.getCancelBackmoney() == 1) {
						CompanyStaffConsume companyStaffConsumeQuery = new CompanyStaffConsume();
						companyStaffConsumeQuery.setOrderId(orderInfo.getId());
                        companyStaffConsumeQuery.setOrderStatus(OrderContants.OrderStatus.WAIT.getIndex());
                        CompanyStaffConsume companyStaffConsume = companyStaffConsumeMapper.selectOne(companyStaffConsumeQuery);
						if (companyStaffConsume != null && companyStaffConsume.getId() != null) {
                            companyStaffConsume.setId(null);
                            companyStaffConsume.setPayTime(null);
                            companyStaffConsume.setCancelTime(new Date());
							companyStaffConsume.setOrderStatus(OrderContants.OrderStatus.CANCEL.getIndex());
							companyStaffConsumeMapper.insertSelective(companyStaffConsume);
						}
						OrderRefund companyOrderRefund = new OrderRefund();
						companyOrderRefund.setOrderId(orderInfo.getId());
						companyOrderRefund.setRefundType(orderInfo.getPayType());// 表示企业退款
						companyOrderRefund.setRefundNo(orderInfo.getOrderNumber());
						companyOrderRefund.setRefundFee(orderInfo.getAmount().doubleValue());
						companyOrderRefund.setTotalFee(orderInfo.getAmount().doubleValue());
						companyOrderRefund.setRefundStatus("success");
						companyOrderRefund.setUserId(orderInfo.getUserId());
						companyOrderRefund.setRefundChanne("companyValuedStoreCard");
						companyOrderRefund.setRefundFashion("1");
						companyOrderRefund.setCreatedTime(new Date());
						companyOrderRefund.setCreatedBy(orderInfo.getUserId().toString());
						companyOrderRefund.setRemark("企业储值卡订单取消退款");
						boolean r = orderInfoMapper.createdRefundOrder(companyOrderRefund) >0;
						log.info("企业储值卡团课订单取消退款 插入数据 ---->" + r);
					}

					// 如果排队订单使用了优惠券，则需要退换优惠券信息
					if (orderInfo.getCouponDetailId() != null) {
						CouponDetail couponDetail = couponDetailMapper
								.selectByPrimaryKey(Long.valueOf(orderInfo.getCouponDetailId()));
						if (couponDetail != null) {
							couponDetail.setIsUsed(0);
							couponDetail.setUseTime(null);
							couponDetailMapper.updateByPrimaryKey(couponDetail);
						}
					}

					// 可退款的消息
					templateSendService.sendAutoCancelWaitOrderTemplate("1", orderInfo);
                }
			}
			log.info("=============autoCancelWaitTeamOrder end=============");
			}catch(Exception e){
				e.printStackTrace();
				log.error("==>>自动取消排队通知任务异常:" + e.getMessage());
			}
		}
	}

    /**
     * java定时器：檬营排队订单，没排上订单改为取消（标记可退款，按截止报名时间）
     *
     * 字段   允许值   允许的特殊字符
     * 秒      0-59    , - * /
     * 分      0-59    , - * /
     * 小时    0-23    , - * /
     * 日期    1-31    , - * ? / L W C
     * 月份    1-12 或者 JAN-DEC    , - * /
     * 星期    1-7 或者 SUN-SAT    , - * ? / L C #
     * 年（可选）    留空, 1970-2099    , - * /
     * - 区间
     * 通配符
     * ? 你不想设置那个字段
     */
    @Scheduled(cron = "1 */5 * * * ?")  //每隔5分钟 执行一次
    public void cancelWaitCampOrder() {

        String TOKEN_UPDATE_FLAG = ManageConfigPropertiesUtil.getString("token_update_flag").trim();

        // 1测试/正式环境才启动定时器
        if ("1".equals(TOKEN_UPDATE_FLAG)) {
            try {
                long startTime = System.currentTimeMillis();
                log.info("檬营取消排队订单定时任务 开始执行--------->>");
                // 查找当前已到截止时间的檬营订单
                List<OrderCourseDetailInfo> orderList = orderInfoMapper.queryCampCourseWaitList();
                log.info("排队订单size --> " + orderList.size());
                Date nowDate;
                for (OrderCourseDetailInfo orderInfo : orderList) {
                    log.info("订单id ====>>>>>" + orderInfo.getId());
                    nowDate = new Date();
                    orderInfo.setOrderStatus(OrderContants.OrderStatus.CANCEL.getStatus());// 订单取消状态
                    orderInfo.setUpdatedTime(nowDate);
                    orderInfo.setUserCancelTime(nowDate);// 取消时间
                    orderInfo.setCancel(2);// 被动取消
                    orderInfo.setUpdatedBy(-1);// 定时器取消
                    orderInfo.setCancelBackmoney(1);// 1可退款标记

                    // 查询对应的课程
                    // 如果存在等待人数 才更新等待人数
                    CourseInfo courseInfo = courseInfoMapper.queryCourseByServiceId(orderInfo.getServiceId());
                    if (courseInfo != null && courseInfo.getWaitCount() != null && courseInfo.getWaitCount() > 0
                            && orderInfo.getOrderDetail() != null
                            && orderInfo.getOrderDetail().getPersonCount() != null) {

                        log.info("课程当前等待人数====>" + courseInfo.getWaitCount());
                        log.info("订单当前购买人数====>" + orderInfo.getOrderDetail().getPersonCount());
                        int waitCount = courseInfo.getWaitCount() - orderInfo.getOrderDetail().getPersonCount();
                        log.info("课程ID ----" + courseInfo.getId() + " 订单人数=====> "
                                + orderInfo.getOrderDetail().getPersonCount());
                        log.info("等待人数 ===> " + waitCount);
                        courseInfo.setWaitCount(waitCount);
                        int updateCount = courseInfoMapper.updateSelectiveById(courseInfo);//updateByPrimaryKeyAndVersionSelective(courseInfo);
                        if (updateCount > 1) {
                            throw new RuntimeException("课程更新数量异常 " + updateCount + "条");
                        }
                    }

                    //企业支付的可退款订单 退款记录
                    if (orderInfo.getPayType() == OrderContants.PAY_TYPE_COMPANY_ACCOUNT && orderInfo.getCancelBackmoney() == 1) {
                        orderInfo.setPayStatus(OrderContants.PayStatus.REFOUND);//标记已退款
                        CompanyStaffConsume companyStaffConsume = companyStaffConsumeMapper.selectCompanyStaffOrderCancel(orderInfo.getId());
                        if (companyStaffConsume != null && companyStaffConsume.getId() != null) {
                            companyStaffConsume.setId(null);
                            companyStaffConsume.setPayTime(null);
                            companyStaffConsume.setCancelTime(new Date());
                            companyStaffConsume.setOrderStatus(OrderContants.OrderStatus.CANCEL.getIndex());
                            companyStaffConsumeMapper.insertSelective(companyStaffConsume);
                        }
                        OrderRefund companyOrderRefund = new OrderRefund();
                        companyOrderRefund.setOrderId(orderInfo.getId());
                        companyOrderRefund.setRefundType(orderInfo.getPayType());// 表示企业退款
                        companyOrderRefund.setRefundNo(orderInfo.getOrderNumber());
                        companyOrderRefund.setRefundFee(orderInfo.getAmount().doubleValue());
                        companyOrderRefund.setTotalFee(orderInfo.getAmount().doubleValue());
                        companyOrderRefund.setRefundStatus("success");
                        companyOrderRefund.setUserId(orderInfo.getUserId());
                        companyOrderRefund.setRefundChanne("companyValuedStoreCard");
                        companyOrderRefund.setRefundFashion("1");
                        companyOrderRefund.setCreatedTime(new Date());
                        companyOrderRefund.setCreatedBy(orderInfo.getUserId().toString());
                        companyOrderRefund.setRemark("企业储值卡订单取消退款");
                        boolean r = orderInfoMapper.createdRefundOrder(companyOrderRefund) >0;
                        log.info("企业储值卡檬营订单取消退款 插入数据 ---->" + r);
                    }
                    // 更新加入乐观锁
                    int updateCount = orderInfoMapper.updateByPrimaryKeyAndVersionSelective(orderInfo);

                    // 如果排队订单使用了优惠券，则需要退换优惠券信息
                    if (orderInfo.getCouponDetailId() != null) {
                        CouponDetail couponDetail = couponDetailMapper
                                .selectByPrimaryKey(Long.valueOf(orderInfo.getCouponDetailId()));
                        couponDetail.setIsUsed(0);
                        couponDetail.setUseTime(null);
                        couponDetailMapper.updateByPrimaryKeySelective(couponDetail);
                    }

                    if (updateCount > 1) {
                        throw new RuntimeException("排队订单更新错误---->更新到" + updateCount + "条课程数据");
                    }
                    log.info("檬营取消排队订单 订单id = " + orderInfo.getId() + " ===>>>>> 变更为取消 ");
                    templateSendService.sendCancelOrderTemplateMsg("1", orderInfo.getId());// 发送订单取消可退款的消息
                }
                long endTime = System.currentTimeMillis();
                log.info("檬营取消排队订单定时任务 执行完成---------<<< 总计耗时" + (endTime - startTime) / DateUtils.MILLIS_PER_SECOND
                        + "秒");
            } catch (Exception ex) {
                ex.printStackTrace();
                log.error("===>>取消檬营排队订单任务异常：" + ex.toString());
            }
        }
    }

	/**
	 * 即将开始30分钟订单发送任务 只包含团课，自助健身
	 */
	@Scheduled(cron = "0 */5 * * * ?") // test每隔5分钟调用
	public void autoUpComingOrder() {
		// 1测试/正式环境才启动定时器
		if ("1".equals(TOKEN_UPDATE_FLAG)) {
			try {
				log.info("=============autoUpComingOrder start=============");
				List<OrderInfoResultModel> orderInfoResultModels = orderInfoResultMapper.selectUpCommingOrderList();
				if (orderInfoResultModels != null && orderInfoResultModels.size() > 0) {
					log.info("autoUpComingOrder size ： " + orderInfoResultModels.size());
					for (OrderInfoResultModel orderInfo : orderInfoResultModels) {
						try {
							templateSendService.sendUpCommingTemplateMsg(orderInfo);
							Map<Object, Object> map = new HashMap<Object, Object>();
							map.put("sendType", "1");
							map.put("orderId", orderInfo.getId());
							map.put("sendTime", new Date());
							orderInfoResultMapper.insertSendTemplateLog(map);
						} catch (Exception e) {
							log.error(e.getMessage());
						}
					}
				}
				log.info("=============autoUpComingOrder end=============");
			} catch (Exception e) {
				e.printStackTrace();
				log.error("==>>即将开始任务异常：" + e.toString());
			}
		}

	}

	/**
	 * 每天18:30开始发送会员即将到期提醒
	 */
//	@Scheduled(cron = "0 0 20 * * ?")
	public void autoVIPUserExpireTips() {
		if ("1".equals(TOKEN_UPDATE_FLAG)) {
			try {
				log.info("=================>> autoVIPUserExpireTips 发送会员订单即将到期任务开始：");
				List<UserInfo> vipUserExpires = userInfoMapper.queryAllExpireVIPUser();
				if (vipUserExpires != null && vipUserExpires.size() > 0) {
					for (UserInfo userInfo : vipUserExpires) {
						try {
							// 发送会员即将到期提醒
							templateSendService.sendVIPExpireTipsTemplate(userInfo);
							// 记录发送日志
							Map<Object, Object> map = new HashMap<Object, Object>();
							map.put("sendType", "3");
							map.put("orderId", userInfo.getId());
							map.put("sendTime", new Date());
							orderInfoResultMapper.insertSendTemplateLog(map);
						} catch (Exception e) {
							log.error("会员即将到期提醒发送错如，错如用户为 ：" + userInfo.getId() + " 错误信息为：" + e.getMessage());
						}
					}
				}
				log.info("=================>> autoVIPUserExpireTips 发送会员订单即将到期任务结束 。");
			} catch (Exception e) {
				e.printStackTrace();
				log.error("==>>会员到期提醒任务异常:" + e.toString());
			}
		}
	}

	/**
	 * 自动发送课表更新推送模板消息
	 */
	@Scheduled(cron = "0 */10 * * * ?")
	public void autoSendUpdateCourseTips() {

		if ("1".equals(TOKEN_UPDATE_FLAG)) {
			try {
				// 查询课表更新最新的一条记录。
				log.info("==================>>课表通知发送开始：");
				CourseNoticeInfo courseNoticeInfo = courseNoticeInfoMapper.queryLastCourseNoticeInfo(1);
				if (courseNoticeInfo != null) {
					updateCourseNoticeInfo(courseNoticeInfo, 2);
					// 查询所有已完成订单的用户信息，剔除重复记录
					List<UserInfo> userInfos = userInfoMapper.queryAllHasOrderUsersBy("4");
					if (userInfos != null) {
						for (UserInfo userInfo : userInfos) {
							// 按用户发送模板消息
							templateSendService.sendUpdateCourseNotice(courseNoticeInfo.getTitle(),
									courseNoticeInfo.getStoreids(), courseNoticeInfo.getSendtime(), userInfo);
						}
					}
					// 已完成发送
					updateCourseNoticeInfo(courseNoticeInfo, 3);
					log.info("==================>>课表通知发送结束：");
				}
			} catch (Exception e) {
				e.printStackTrace();
				log.error("==>>自动发送课表通知异常：" + e.toString());
			}
		}
	}

	private void updateCourseNoticeInfo(CourseNoticeInfo courseNoticeInfo,int sendFlag) {
		courseNoticeInfo.setSendFlag(sendFlag);
		courseNoticeInfo.setUpdateBy(-1);
		courseNoticeInfo.setUpdateTime(new Date());
		courseNoticeInfoMapper.updateSelectiveById(courseNoticeInfo);
	}


	/**
	 * 90分钟开课自动通知上课教练短信
	 *
	 */
	@Scheduled(cron = "0 */5 * * * ?")
	public void autoSendClassNotification(){

		if ("1".equals(TOKEN_UPDATE_FLAG)) {
            long timeStart = System.currentTimeMillis();
            log.info("发送教练团课90分钟开课通知短信定时任务 开始执行--------->>");

			//查询所有即将在90分钟之内开始的课程
			List<CoachCourseInfo> courseInfoList = courseInfoMapper.queryCoachCourseNotificationList();
			for (CoachCourseInfo coach : courseInfoList) {
                //查询是否已经发送过 通知信息 如已发过则跳过不再发送
                SmsLog smsLog = new SmsLog();
                smsLog.setSendType(4);
                smsLog.setSendResult(1);
//                smsLog.setUserId(coach.getUserId());//解决多人订购同一课程导致教练端收到同一课程的重复短信的问题
				smsLog.setCourseId(coach.getCourseId());
				smsLog.setMobile(coach.getCoachMobile());
                EntityWrapper<SmsLog> smsLogEntityWrapper = new EntityWrapper<>();
                smsLogEntityWrapper.setEntity(smsLog);
                List<SmsLog> smsLogList = smsLogMapper.selectList(smsLogEntityWrapper);
                if (smsLogList !=null && smsLogList.size() > 0) {
                    continue;
                }
                boolean sendResult = SmsUtil.sendCoachCourse90MinNotificationSms(
                        coach.getCoachMobile(), coach.getCoachName(), "课程",
                        DateUtil.formatDate(coach.getCourseStartTime(), DateUtil.FMT_DATE_MMDD_HHMM), coach.getStoreName());
                //发送记录
                SmsLog smsLogRec = new SmsLog();
                smsLogRec.setMobile(coach.getCoachMobile());
                smsLogRec.setStoreName(coach.getStoreName());
//                smsLogRec.setUserId(coach.getUserId());
                smsLogRec.setCourseId(coach.getCourseId());
                smsLogRec.setSendTime(new Date());
                smsLogRec.setSendResult(sendResult ? 1 : 2);
                smsLogRec.setSendType(4);
                smsLogMapper.insertSelective(smsLogRec);
                log.info("发送教练团课90分钟开课通知短信 -->" + smsLogRec.toString());
			}
            long timeEnd = System.currentTimeMillis();
            log.info("发送教练团课90分钟开课通知短信定时任务 执行完成---------<<< 总计耗时"+ (timeEnd - timeStart)/ DateUtils.MILLIS_PER_SECOND + "秒" );

		}

	}
	
	/**
	 * 自助健身年卡到期自动提醒
	 */
	@Scheduled(cron = "0 0 20 * * ?")
//	@Scheduled(cron = "0 */5 * * * ?")
	public void autoSelfServiceExpireTips() {
		
		try {
			log.info("=================>> autoSelfServiceExpireTips 发送会员订单即将到期任务开始：");
			List<UserProductService> userProductServiceList = userInfoMapper.queryAllExpireSelfServiceUser();
			if (userProductServiceList != null && userProductServiceList.size() > 0) {
				for (UserProductService uerProductService : userProductServiceList) {
					try {
						// 发送年卡即将到期提醒
						templateSendService.sendSelfExpireTipsTemplate(uerProductService);
						// 记录发送日志
						Map<Object, Object> map = new HashMap<Object, Object>();
						map.put("sendType", "6");
						map.put("orderId", uerProductService.getUserId());
						map.put("sendTime", new Date());
						orderInfoResultMapper.insertSendTemplateLog(map);
					} catch (Exception e) {
						log.error("自助年卡即将到期提醒发送错如，错如用户为 ：" + uerProductService.getUserId() + " 错误信息为：" + e.getMessage());
					}
				}
			}
			log.info("=================>> autoSelfServiceExpireTips 发送会员订单即将到期任务结束 。");
		} catch (Exception e) {
			e.printStackTrace();
			log.error("==>>年卡到期提醒任务异常:" + e.toString());
		}
		if ("1".equals(TOKEN_UPDATE_FLAG)) {
			
		}
	}
}
